/*************************************************
Name : CaseEscalator
Created By : dthekumparampil
Created Date : Feb 7, 2013
Description : 	An Apex class created to escalate the priority of Cases based on CaseNames (Custom Settings).
				.
********************************
Modified By : 
Modified Date : 
Modification : 	
*************************************************/


global class CaseEscalator implements Database.Batchable<sObject>, Database.Stateful{ 
	
	global String caseRecordType = Schema.Sobjecttype.Case.getRecordTypeInfosByName().get('West - Support').getRecordTypeId();
	global String caseADARecordType = Schema.Sobjecttype.Case.getRecordTypeInfosByName().get('West - ADA Support').getRecordTypeId();
	global map<String, Integer> escalationDeadlines = new map<String, Integer>();
	global String businessHourId; 

	global Database.Querylocator start(Database.BatchableContext bc){ 
		
		/****Creating a map containing the CaseNames and their corresponding Escalation Deadlines****/
		list <West_Case_Names__c> listOfCaseNames = West_Case_Names__c.getAll().values();
		for(integer index=0; index< listOfCaseNames.size(); index++){
			escalationDeadlines.put(listOfCaseNames[index].Name,listOfCaseNames[index].West_Case_Type_Deadline__c.intValue());
		}
		
		/****Retrieves the Business Hour Id ****/
		businessHourId = [select id, Name from BusinessHours where Name = 'West Phoenix Business Hours' LIMIT 1].id;

		/****String which retrives all Cases (of West), for which the West_Business_Age_Flag__c is not set to true. ****/
		String query = 'select id, status, Priority, West_Business_Age_Flag__c, West_Business_Age__c, CreatedDate, ClosedDate, Case_Name__c, Prior_Escalations__c from Case where West_Business_Age_Flag__c= false AND (RecordTypeId =\''+caseRecordType+'\' OR RecordTypeId = \''+caseADARecordType+'\')';
		System.debug('The Query in start is:>>>>'+query);

		return Database.getQuerylocator(query);
	}
		
	/****
	In the below code, first the age of each case is calculated based on the defined business hour.
	If the case is closed, then the West_Business_Age__c field is updated and the West_Business_Age_Flag__c is set as true.
	If not closed, Escalation Logic is run and the case priority is escalated if required.
	****/
	global void execute(Database.BatchableContext bc, list<Case> listOfCases){
		
		Map<String,West_Case_Names__c> mapCaseCustSettingReferenceObject = new Map<String,West_Case_Names__c>();
		List<Case> lstOfCasesToUpdate = new List<Case>();
		mapCaseCustSettingReferenceObject = West_Case_Names__c.getAll();
		
		for(Integer index=0; index< listOfCases.size(); index++){
			if(mapCaseCustSettingReferenceObject.containsKey(listOfCases[index].Case_Name__c)){
				/*Retrieving the Escalation Deadlines for this case based on CaseName*/
				Integer caseEscalationDeadline = escalationDeadlines.get(listOfCases[index].Case_Name__c);
				
				/*Finding the age of Case (in hours) based on the business hour defined*/
				Integer ageOfCase = (BusinessHours.diff(businessHourId, listOfCases[index].CreatedDate, Datetime.now())/3600000).intValue();
				
				/*If the case is closed, just update the business hour age of case and set the West_Business_Age_Flag__c flag*/
				if(listOfCases[index].status=='Closed'){
					listOfCases[index].West_Business_Age_Flag__c = true;
					listOfCases[index].West_Business_Age__c = ((BusinessHours.diff(businessHourId, listOfCases[index].CreatedDate, listOfCases[index].ClosedDate))/3600000).intValue();
				}
				else{
					/*Run escalation logic only if age of case is greater than or equal to the case escalation deadline value*/
					if(ageOfCase>=caseEscalationDeadline){
						/*
						The number of escalations required is decided by the number of times the escalation Deadline has been crossed
						MINUS the number of times it has already been escalated.
						*/
						 Integer numberOfEscalations = ((ageOfCase/caseEscalationDeadline) - listOfCases[index].Prior_Escalations__c).intValue() ;
						 
						 if(numberOfEscalations >0){
						 	/*Checking if the priority would cross the max if bumped as per the numberOfEscalations required*/
						 	if(Integer.valueOf(listOfCases[index].Priority) - numberOfEscalations >0){
						 		listOfCases[index].Priority = String.valueOf(Integer.valueOf(listOfCases[index].Priority) - numberOfEscalations);
						 	}
						 	else{
						 		listOfCases[index].Priority = '1';
						 	}
						 	/*The Prior_Escalations__c is updated for next time. */
						 	listOfCases[index].Prior_Escalations__c += numberOfEscalations; 
						 }	
					}
					listOfCases[index].West_Business_Age__c = ageOfCase;
				}
				lstOfCasesToUpdate.add(listOfCases[index]);
			}
		}
		update 	lstOfCasesToUpdate;
	}
	
	global void finish(Database.BatchableContext bc){
		
		/****
		No finish logic. 
		****/
		
		
	}

}